# -*- coding: utf-8 -*-
"""
@Time： 2023/12/20 16:20
@Auth： gubei
@File： server.py
@IDE：PyCharm
@Description：服务器初始化项目
"""
import warnings
from pathlib import Path as PyPath
import platform

from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError
from sqlalchemy.exc import SQLAlchemyError
from starlette.staticfiles import StaticFiles
from tortoise.contrib.fastapi import register_tortoise

from core.db.database import engine
from core.exceptions.handlers import (
    validation_exception_handler,
    sqlalchemy_exception_handler,
    pydantic_validation_handler,
    generic_exception_handler
)
from core.log import logger
from core.middlerwares.middleware import middleware
from core.models import models
from core.router import v1
from core.timer import scheduler
from env import setting

from utils.get_local_ip import local_ip
from utils.use_loacl_static import use_local_static


class InitializeApp(object):
    """
    注册App
    """

    current_project_path = PyPath(__file__).resolve().parent.parent  # 获取当前项目根目录路径
    static_templates_path = current_project_path / "templates" / "static"  # 拼接路径

    def __new__(cls, *args, **kwargs):
        # 屏蔽警告
        app = FastAPI(title=setting.APP_TITLE, description=setting.APP_DESCRIPTION, middleware=middleware)
        app.mount("/static", StaticFiles(directory=cls.static_templates_path), name="static")

        # 注册异常处理器
        cls.register_exception_handlers(app)
        
        cls.event_init(app)
        cls.register_router(app)
        return app
    
    @staticmethod
    def register_exception_handlers(app: FastAPI) -> None:
        """
        注册全局异常处理器
        :param app: FastAPI实例
        :return: None
        """
        app.add_exception_handler(RequestValidationError, validation_exception_handler)
        app.add_exception_handler(SQLAlchemyError, sqlalchemy_exception_handler)
        app.add_exception_handler(ValidationError, pydantic_validation_handler)
        app.add_exception_handler(Exception, generic_exception_handler)

    @staticmethod
    def register_router(app: FastAPI) -> None:
        """
        注册路由
        :param app:
        :return:
        """
        # 项目API
        app.include_router(
            v1.ApiRouter(),
        )

    @staticmethod
    def event_init(app: FastAPI) -> None:
        """
        事件初始化
        :param app:
        :return:
        """

        @app.on_event("startup")
        async def startup():
            # 根据环境显示不同的启动模式
            is_debug = platform.system() == "Windows"
            mode = "DEBUG" if is_debug else "PRO"
            logger.bind(name=None).opt(ansi=True).success(f"Project is running at {mode}")

            # 屏蔽警告
            warnings.filterwarnings("ignore", category=Warning)

            # 使用本地静态资源
            use_local_static()

            # 如果是调试模式，初始化数据库表结构
            if is_debug:
                # 在数据库中生成表结构
                models.Base.metadata.create_all(bind=engine)

            scheduler.start()  # 定时任务
            
            # 根据环境使用不同的 IP 展示方式
            display_ip = local_ip if is_debug else setting.APP_HOST
            # logger.info(f"项目启动成功，文档地址：http://{display_ip}:{setting.APP_PORT}/docs")

        @app.on_event('shutdown')
        async def shutdown():
            """
            关闭
            :return:
            """
            # await mysql.close_mysql()
            scheduler.shutdown()
